﻿using Enter.Admin.Entities;
using Enter.Admin.Enums;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Enter.Admin.Utils
{

    [AttributeUsage(AttributeTargets.Field, Inherited = true)]
    public class ValueAttribute : Attribute
    {
        public ValueAttribute()
        {
        }
        public string Value { get; set; }
    }

    [AttributeUsage(AttributeTargets.Enum, Inherited = true)]
    public class SelectListItemAttribute : Attribute
    {
        public SelectListItemAttribute()
        {
        }
        public string Text { get; set; }
        public string Value { get; set; }
        public bool Selected { get; set; }
        public int Order { get; set; }
    }

    public class Tools
    {
        public static string NewGuid()
        {
            var ids = Guid.NewGuid().ToString().Split("-");
            ids[0] = DateTime.Now.ToString("yyyyMMdd");
            return string.Join("-", ids);
        }

        public static List<SelectListItem> EnumList(string enumName,bool insert = true)
        {
            var new_items = new List<SelectListItem>();
            EnumsExt.EnumMap.TryGetValue(enumName, out var items);
            if (insert)
            {
                new_items.Add(new SelectListItem { Value = "", Text = "请选择", Selected = true });
            }
            foreach (var item in items)
            {
                new_items.Add(item);
            }
            return new_items;
        }

        // @Html.EnumDropDownListFor
        // https://github.com/lukkarip/KulujenSeuranta/blob/5dd38953eebe3d39ce590bc0ac0eb19dab43d22d/KulujenSeuranta/Helpers/HtmlHelper.EnumDropDownListFor.cs
        public static List<SelectListItem> EnumList<T>(bool insert = true) where T : Enum
        {
            var enumType = typeof(T);
            return EnumList(enumType, insert);
        }

        public static List<SelectListItem> EnumList(Type enumType,bool insert = true)
        {
            List<SelectListItem> list = new List<SelectListItem>();
            FieldInfo[] fields = enumType.GetFields();
            foreach (FieldInfo field in fields)
            {
                if (!field.FieldType.IsEnum)
                    continue;
                string value = ((int)field.GetValue(null)).ToString();
                {
                    var attr = field.GetCustomAttribute(typeof(ValueAttribute)) as ValueAttribute;
                    if (attr != null)
                    {
                        value = attr.Value;
                    }
                }
                string text = field.Name;
                {
                    // field.IsDefined(typeof(DisplayAttribute), true)
                    var attr = field.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
                    if (attr != null)
                    {
                        text = attr.Name;
                    }
                }
                list.Add(new SelectListItem { Value = value.ToString(), Text = text });//((int)e).ToString() 
            }
            if (insert) 
            {
                var items = enumType.GetCustomAttributes<SelectListItemAttribute>();
                if (items != null)
                {
                    foreach (var item in items)
                    {
                        var order = item.Order;
                        if (item.Order < 0)
                        {
                            order = list.Count + 1 + item.Order;
                        }
                        list.Insert(order, new SelectListItem { Value = item.Value, Text = item.Text, Selected = item.Selected });
                    }
                }
            }
            return list;
        }

        public static string ToString(object obj, string format, bool isDrop = false) 
        {
            if (obj == null) return string.Empty;
            var t = obj.GetType();
            var o_val = string.Empty;
            
            if (t.IsEnum)
            {
                o_val = Convert.ToString(obj);
                if (o_val == "0")
                {
                    // 处理枚举不是从0开始;
                    o_val = string.Empty;
                }
            }
            else if (isDrop)
            {
                o_val = Convert.ToString(obj);
                var item = EnumList(format).Where(t => t.Value == o_val).FirstOrDefault();
                if (item == null)
                {
                    o_val = string.Empty;
                }
                else
                { 
                    o_val = item.Text;
                }
            }
            else
            {
                switch (Type.GetTypeCode(t))
                {
                    case TypeCode.DateTime:

                        if (string.IsNullOrWhiteSpace(format))
                        {
                            format = "yyyy-MM-dd";// HH:mm:ss
                        }
                        // 转换
                        {
                            DateTime data = (DateTime)obj;
                            if (data == DateTime.MinValue) o_val = null;
                            else  o_val = data.ToString(format);
                        }
                        break;
                    case TypeCode.Boolean:
                        if (string.IsNullOrWhiteSpace(format))
                        {
                            format = "是:否";
                        }
                        var tfs = format.Split(":");
                        // 转换
                        {
                            bool data = (bool)obj;
                            if (data)
                            {
                                o_val = tfs[0];
                            }
                            else
                            {
                                o_val = tfs[1];
                            }
                        }
                        break;
                    default:
                        o_val = Convert.ToString(obj);
                        break;
                }
            }
            return o_val;
        }

        //public static bool IsPhone()
        //{ 
        //}

        public static List<string> UpdatedFeils<T>(T obj, List<string> checkFeils = null)
        {
            List<string> updatedFeils = new List<string>();
            var properties = typeof(T).GetProperties().ToList();
            if (checkFeils != null && checkFeils.Count > 0)
            {
                properties = properties.Where(t => checkFeils.Contains(t.Name)).ToList();
            }
            foreach (var prop in properties)
            {
                var feild = prop.GetValue(obj, null);
                if (feild == null)
                {
                    continue;
                }
                var cell_string = feild.ToString().Trim();
                var pt_code = Type.GetTypeCode(prop.PropertyType);
                if (pt_code == TypeCode.DateTime)
                {
                    var v = (DateTime)feild;
                    if (v != DateTime.MinValue)
                    {
                        updatedFeils.Add(prop.Name);
                    }
                }
                else if (prop.PropertyType.IsEnum || pt_code == TypeCode.Int32 || pt_code == TypeCode.Int64 || pt_code == TypeCode.Decimal)
                {
                    if (!string.IsNullOrEmpty(cell_string) && cell_string != "0")
                    {
                        updatedFeils.Add(prop.Name);
                    }
                }
                else if (!string.IsNullOrWhiteSpace(cell_string))
                {
                    updatedFeils.Add(prop.Name);
                }
            }
            return updatedFeils;
        }
    }

    public static class SettingExt
    {
        public static T To<T>(this List<Setting> list){
            var t_type = typeof(T);
            T temp = (T)Activator.CreateInstance(t_type);
            list.ForEach(item=>{
                var prop = t_type.GetProperty(item.Key);
                var obj = Convert.ChangeType(item.Value, prop.PropertyType);
                prop.SetValue(temp, obj);
            });
            return temp;
        }

        public static T To<T>(IFreeSql _fsql, EnumSettingType type){
            return _fsql.Select<Setting>().Where(t=>t.SettingType == type).ToList().To<T>();
        }
    }
}
